package com.zx.idc.backend.gui.api.management.infosecurity.activeresources.service.impl;

import com.zx.idc.backend.gui.api.commom.entity.UploadModel;
import com.zx.idc.backend.gui.api.commom.template.NIdcFtpTemplate;
import com.zx.idc.backend.gui.api.management.infosecurity.activeresources.base.BaseActiveResourceService;
import com.zx.idc.backend.gui.api.management.infosecurity.activeresources.base.pojo.ActiveResourceData;
import com.zx.idc.backend.gui.api.management.infosecurity.activeresources.base.pojo.ReportDate;
import com.zx.idc.backend.gui.api.management.infosecurity.activeresources.service.ActiveResourceService;
import com.zx.idc.cache.entity.HotDomainMetaInfo;
import com.zx.idc.cache.entity.HotIpMetaInfo;
import com.zx.idc.cache.slog.SlogHotDomainCacheService;
import com.zx.idc.cache.slog.SlogHotIpCacheService;
import com.zx.idc.common.attributes.FTPReportDataTypeEnum;
import com.zx.idc.common.attributes.NetCommunicationFileTypeEnum;
import com.zx.idc.common.attributes.SchemaFileNameEnum;
import com.zx.idc.common.configuration.AppProtocolConfiguration;
import com.zx.idc.common.constants.IsInIpSegConstants;
import com.zx.idc.common.function.Rogue;
import com.zx.idc.common.lang.ListUtil;
import com.zx.idc.common.util.TimeConversionUtils;
import com.zx.idc.ds.base.oper.service.IBaseOperCompanyService;
import com.zx.idc.ds.common.constant.ReportStatusConstant;
import com.zx.idc.ds.slog.service.ISlogHotDomainService;
import com.zx.idc.ds.slog.service.ISlogHotIpService;
import com.zx.idc.ds.upload.vo.UploadHotDomainVo;
import com.zx.idc.ds.upload.vo.UploadHotIpVo;
import com.zx.idc.xml.entity.activeresources.ActiveResources;
import com.zx.idc.xml.entity.activeresources.finddomainlist.FindDomainList;
import com.zx.idc.xml.entity.activeresources.findiplist.FindIpList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Created by hasee on 2019/2/18.
 * 活跃资源监测数据上报内容
 * 主动上报 定时任务
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ActiveResourceServiceImpl implements ActiveResourceService {

    private static final Logger LOG = LoggerFactory.getLogger(ActiveResourceServiceImpl.class);

    @Autowired
    private NIdcFtpTemplate nIdcFtpTemplate;

    @Autowired
    private BaseActiveResourceService findDomainListServiceImpl;

    @Autowired
    private BaseActiveResourceService findIpListServiceImpl;

    @Autowired
    private ISlogHotIpService iSlogHotIpService;

    @Autowired
    private ISlogHotDomainService iSlogHotDomainService;

    @Autowired
    private SlogHotDomainCacheService slogHotDomainCacheService;

    @Autowired
    private SlogHotIpCacheService slogHotIpCacheService;

    @Autowired
    private IBaseOperCompanyService iBaseOperCompanyService;

    /***********************************活跃域名 活跃url上报开始****************************************/


    /**
     * 活跃域名 活跃IP主动上报(调度任务调用)
     */
    @Override
    public void activeResources() {
        //读出前一天的文件夹，读出信息上报
        ActiveResourceData<ActiveResources> domainActiveResources = getHotDomainActiveResources();
        ActiveResourceData<ActiveResources> hotIpActiveResources = getHotIpActiveResources();
        ActiveResources hotDomainData = domainActiveResources.getData();
        ActiveResources hotIpData = hotIpActiveResources.getData();
        //更新上报状态为上报中
        if (ListUtil.isNotEmpty(hotDomainData.getFindDomainList())) {
            uploadOperating(domainActiveResources, () -> updateReportStatus(hotDomainData, ReportStatusConstant.REPORTING));
        }

        if (ListUtil.isNotEmpty(hotIpData.getFindIpList())) {
            uploadOperating(hotIpActiveResources, () -> updateReportStatus(hotIpData, ReportStatusConstant.REPORTING));
        }
    }

    /**
     * 上报的操作
     *
     * @param activeResources 上报数据
     * @param uploadBeforeFn 上报之前执行的函数
     */
    private void uploadOperating(ActiveResourceData<ActiveResources> activeResources, Rogue uploadBeforeFn) {
        ActiveResources data = activeResources.getData();
        uploadBeforeFn.accept();
        nIdcFtpTemplate.uploadXMLFile(
            new UploadModel<>(
                data,
                SchemaFileNameEnum.ACTIVE_RESOURCE_REPORT,
                FTPReportDataTypeEnum.FTP_ACTIVE_RESOURCE_MONITORING_RECORD,
                NetCommunicationFileTypeEnum.ACTIVE_RESOURCE
            )
        );
        activeResources.getPaths().forEach(path ->
            {
                try {
                    Files.deleteIfExists(Paths.get(path));
                } catch (IOException ignored) {
                }
            }
        );
    }

    /**
     * 活跃域名 活跃url上报(后台调用)
     * @param activeResources
     */
    @Override
    public void reportData(ActiveResources activeResources) {
        //修改上报状态为上报中
        updateReportStatus(activeResources, ReportStatusConstant.REPORTING);

        nIdcFtpTemplate.uploadXMLFile(
            new UploadModel<>(
                activeResources,
                SchemaFileNameEnum.ACTIVE_RESOURCE_REPORT,
                FTPReportDataTypeEnum.FTP_ACTIVE_RESOURCE_MONITORING_RECORD,
                NetCommunicationFileTypeEnum.ACTIVE_RESOURCE
            )
        );
    }

    /**
     * ？更新上报状态 只更新活跃域名和活跃ip的数据
     *
     * @param data
     * @param reportStatus
     */
    private void updateReportStatus(ActiveResources data, Integer reportStatus) {
        //修改数据库状态
        List<FindDomainList> findDomainList = data.getFindDomainList();
        if (ListUtil.isNotEmpty(findDomainList)) {
            iSlogHotDomainService.updateBatchReportStatus(findDomainList, reportStatus);
        }

        List<FindIpList> findIpList = data.getFindIpList();
        if (ListUtil.isNotEmpty(findIpList)) {
            iSlogHotIpService.updateBatchReportStatus(findIpList, reportStatus);
        }
    }

    /**
     * 获取活跃域名上报数据
     *
     * @return
     */
    private ActiveResourceData<ActiveResources> getHotDomainActiveResources() {
        //获取活跃域名信息
        ReportDate<UploadHotDomainVo> uploadHotDomainVos = findDomainListServiceImpl.getReportDate();

        return new ActiveResourceData<ActiveResources>()
            .setData(
                new ActiveResources().setFindDomainList(
                    getFindDomainList(uploadHotDomainVos.getData())
                )
            )
            .setPaths(uploadHotDomainVos.getFilePaths());
    }

    /**
     * 获取活跃IP上报数据
     *
     * @return
     */
    private ActiveResourceData<ActiveResources> getHotIpActiveResources() {
        //获取活跃IP信息
        ReportDate<UploadHotIpVo> uploadHotIpVos = findIpListServiceImpl.getReportDate();

        return new ActiveResourceData<ActiveResources>()
            .setData(
                new ActiveResources().setFindIpList(
                    getFindIpList(uploadHotIpVos.getData())
                )
            )
            .setPaths(uploadHotIpVos.getFilePaths());
    }

    private List<FindDomainList> getFindDomainList(List<UploadHotDomainVo> uploadHotDomains) {
        String idcId = iBaseOperCompanyService.getIdcId();
        return uploadHotDomains.stream()
            .peek(uploadHotDomain -> {
                HotDomainMetaInfo meta = slogHotDomainCacheService.getMeta(Long.valueOf(uploadHotDomain.getHouseId()), uploadHotDomain.getFindDomainListDomain());
                if (Objects.nonNull(meta)) {
                    Optional.ofNullable(meta.getVisitCnt()).ifPresent(visitCnt ->
                        uploadHotDomain.setVisitsCount(Math.toIntExact(visitCnt))
                    );
                    Optional.ofNullable(meta.getLstFoundTime()).ifPresent(uploadHotDomain::setLastTime);
                }
            })
            .map(uploadHotDomain ->
                new FindDomainList()
                    .setFindDomainListDomain(uploadHotDomain.getFindDomainListDomain())
                    .setFindDomainListFirstTime(TimeConversionUtils.date2LocalDateTime(uploadHotDomain.getFirstTime()))
                    .setFindDomainListLastTime(TimeConversionUtils.date2LocalDateTime(uploadHotDomain.getLastTime()))
                    .setVisitsCount(uploadHotDomain.getVisitsCount())
                    .setBlock(Integer.valueOf(uploadHotDomain.getBlock()))
                    .setTopDomainflag(Integer.valueOf(uploadHotDomain.getTopDomainflag()))
                    .setTopDomain(uploadHotDomain.getTopDomain())
                    .setIp(uploadHotDomain.getIp())
                    .setIdcId(idcId)
                    .setHouseId(Long.parseLong(uploadHotDomain.getHouseId()))
        ).collect(Collectors.toList());
    }

    private List<FindIpList> getFindIpList(List<UploadHotIpVo> uploadHotIps) {
        String idcId = iBaseOperCompanyService.getIdcId();
        return uploadHotIps.stream()
            .peek(uploadHotIp -> {
                HotIpMetaInfo meta = slogHotIpCacheService.getMeta(Long.valueOf(uploadHotIp.getHouseId()), uploadHotIp.getFindIpListIp());
                if (Objects.nonNull(meta)) {
                    Optional.ofNullable(meta.getVisitCnt()).ifPresent(visitCnt ->
                        uploadHotIp.setVisitsCount(Math.toIntExact(visitCnt))
                    );
                    Optional.ofNullable(meta.getLstFoundTime()).ifPresent(uploadHotIp::setLastTime);
                }
            })
            .map(uploadHotIp ->
                new FindIpList()
                    .setFindIpListIp(uploadHotIp.getFindIpListIp())
                    .setFindIpListFirstTime(TimeConversionUtils.date2LocalDateTime(uploadHotIp.getFirstTime()))
                    .setFindIpListLastTime(TimeConversionUtils.date2LocalDateTime(uploadHotIp.getLastTime()))
                    .setBlock(Integer.valueOf(uploadHotIp.getBlock()))
                    .setVisitsCount(uploadHotIp.getVisitsCount())
                    .setIsInIpSeg(getIsIpSeg(uploadHotIp.getIsInIpSeg()))
                    .setPort(uploadHotIp.getPort())
                    .setProtocol(Integer.valueOf(uploadHotIp.getProtocol()))
                    .setIdcId(idcId)
                    .setHouseId(Long.parseLong(uploadHotIp.getHouseId()))
        ).collect(Collectors.toList());
    }

    /**
     * 获取报备状态
     *
     * @param isInIpSeg
     * @return
     */
    private Integer getIsIpSeg(String isInIpSeg) {
        if (String.valueOf(ReportStatusConstant.NOT_REPORTED).equals(isInIpSeg)) {
            return IsInIpSegConstants.NOT_REPORT;
        }
        return IsInIpSegConstants.REPORTED;
    }




}
